/*
 * Created by: 
 * Created: Wednesday, April 18, 2007
 */

using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web.UI;
using Edge.Common.ControlFlow;
using Edge.Common.TextTemplates.Exceptions;
using Edge.Common.ControlFlow;
using Edge.Common.TextTemplates.Exceptions;

namespace Edge.Common.TextTemplates.Impl.ASPNET
{
    public class ControlRenderer
    {
        private Control control;
        private bool rendered = false;

        public ControlRenderer(Control control)
        {
            if (control == null)
                throw new ArgumentException("control");
            this.control = control;
        }

        private void Prepare(StringBuilder stringBuilder, ref HtmlTextWriter html)
        {
            rendered = true;

            UserControl userControl = control as UserControl;
            if (userControl != null)
                userControl.InitializeAsUserControl(null);

            IPrepareSupport prepareSupport = control as IPrepareSupport;
            if (prepareSupport != null)
                prepareSupport.Prepare();

            html = new HtmlTextWriter(new StringWriter(stringBuilder));

            //            ReflectionUtils.Invoke(control, "InitRecursive", new object[] { null });
            //            ReflectionUtils.Invoke(control, "LoadRecursive");

            MethodInfo mi = typeof(Control).GetMethod("EnsureOccasionalFields", BindingFlags.Instance | BindingFlags.NonPublic);
            Assert.CheckNotNull(mi);
            mi.Invoke(control, new object[] { });
        }

        public void Render(StringBuilder stringBuilder, IServiceProvider serviceProvider)
        {
            if (rendered)
                throw new InvalidOperationException("Control already rendered");

            try
            {
                HtmlTextWriter html = null;
                Prepare(stringBuilder, ref html);

                if (serviceProvider != null)
                    control.Site = new Site(serviceProvider);

                if (control.Site != null)
                    SetupSiteControls(control);

                control.RenderControl(html);
                html.Flush();
            }
            catch (Exception ex)
            {
                throw new RenderTemplateException("Error at rendering template", ex);
            }
        }

        private void SetupSiteControls(Control control)
        {
            foreach (Control cnt in control.Controls)
            {
                cnt.Site = control.Site;
                if (cnt.Controls.Count > 0)
                    SetupSiteControls(cnt);
            }
        }

        public void Render(StringBuilder stringBuilder)
        {
            if (rendered)
                throw new InvalidOperationException("Control already rendered");

            try
            {
                HtmlTextWriter html = null;
                Prepare(stringBuilder, ref html);

                control.RenderControl(html);
                html.Flush();
            }
            catch (Exception ex)
            {
                throw new RenderTemplateException("Error at rendering template", ex);
            }
        }

    }
}